package app1

import com.netflix.config.ConfigurationManager
import com.netflix.hystrix.Hystrix
import com.netflix.hystrix.HystrixCircuitBreaker
import com.netflix.hystrix.HystrixCommandKey
import com.netflix.hystrix.HystrixCommandMetrics
import grails.testing.mixin.integration.Integration
import org.springframework.beans.factory.annotation.Autowired
import spock.lang.Specification

@Integration
@grails.gorm.transactions.Rollback
class SampleApiServiceSpec extends Specification {

    private static final CommandKey = "SampleApiService#process(String)"

    @Autowired
    private SampleApiService sampleApiService

    def setupSpec() {
        Hystrix.reset()
    }

    def setup() {
    }

    def cleanup() {
    }

    void "test fallbackMethod"() {
        given:
        def dependency = "gateway"

        when: "The circuit breaker is open when call the method 'process'."
        def result = sampleApiService.process("fakeToken123", dependency)

        then:
        result instanceof Map
        result.state == "offline"
        result.provider == "sampleApi1@serviceSet1"
        result.dependency == dependency
    }

    void "shouldTripCircuit"() {
        given:
        ConfigurationManager.getConfigInstance().setProperty("hystrix.command.${CommandKey}.circuitBreaker.requestVolumeThreshold", 1)
        HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory.getInstance(HystrixCommandKey.Factory.asKey(CommandKey))

        when: "nothing to do"

        // demonstrates circuit is actually closed
        then:
        !circuitBreaker.isOpen()
        circuitBreaker.allowRequest()

        when:
        sampleApiService.process("fakeToken123", "gateway")

        and:
        /*
        waitUntilCircuitBreakerOpens
        one second is almost sufficient
        borrowed from https://github.com/Netflix/Hystrix/blob/v1.5.5/hystrix-core/src/test/java/com/netflix/hystrix/HystrixCircuitBreakerTest.java#L140
         */
        sleep 1000

        then:
        circuitBreaker.isOpen()
        !circuitBreaker.allowRequest()
    }

    void "shouldHaveCustomTimeout"() {
        expect: "Check timeoutInMilliseconds flow the custom by @HystrixCommand.commandProperties or default configuration"
        HystrixCommandMetrics.getInstance(HystrixCommandKey.Factory.asKey(CommandKey)).getProperties().executionTimeoutInMilliseconds().get() == 1200
    }
}
